#include "spit_param.h"

#include "defs.grpc.pb.h"
#include "msg_def.h"

#include "gp_layout_map.h"
#include "motor_config.h"

using namespace google::protobuf;

int divideSpitPos(const void * paramIn,int paramTypeIn,pos_type_list * paramListOut,int *totalSpitVolume)
{
   const RepeatedPtrField<GPRPC::MoveLiquidParam> * spitParamArr = NULL;
   int posSize = 0;
   const GPRPC::DjDpSuckMoreSpitParam* pstLiquidCtlParamTmp = NULL;
   if(PARAM_LIQUID_CTL==paramTypeIn)
   {
        const GPRPC::DjDpLiquidCtrlParam* pstLiquidCtlParam = (GPRPC::DjDpLiquidCtrlParam*)paramIn;   
        //volume = pstLiquidCtlParam->volum();
        spitParamArr = &(pstLiquidCtlParam->moveliquidparam());
        posSize = pstLiquidCtlParam->moveliquidparam_size();
   }
   else if(PARAM_SUCK1_SPIT_MULTI == paramTypeIn)
   {
        const GPRPC::DjDpSuckMoreSpitParam* pstLiquidCtlParam = (GPRPC::DjDpSuckMoreSpitParam*)paramIn;
        pstLiquidCtlParamTmp = pstLiquidCtlParam;

        spitParamArr = &(pstLiquidCtlParam->spiteparam());
        posSize = pstLiquidCtlParam->spiteparam_size();

   }
   int spitVolume = 0;

   paramListOut->listHead = NULL;
   paramListOut->listTail = NULL;
   if(posSize<=0)
   {
       *totalSpitVolume = spitVolume;
       return 2;
   }
   printf("posSize=%d\n",posSize);
   for(int i=0;i<posSize;i++)
   {
       if((*spitParamArr)[i].volum()<=0)
       {
          continue;
       }
       pos_spit * nodeSpitPos = new pos_spit;
       memset(nodeSpitPos,0,sizeof(pos_spit));
       nodeSpitPos->column_x = (*spitParamArr)[i].pos().column();
       nodeSpitPos->row_y = (*spitParamArr)[i].pos().row();
       nodeSpitPos->index = (*spitParamArr)[i].pos().index();
       nodeSpitPos->volume = (*spitParamArr)[i].volum();
       
	   spitVolume += spitVolume;
       printf("in divideSpitPos,i=%d, index:%d,column:%d,row:%d\n",i,nodeSpitPos->index,nodeSpitPos->column_x,nodeSpitPos->row_y);
       
       pos_one_type * ptrOneType = findPosType(paramListOut,(*spitParamArr)[i].pos().postype());
       
       if(ptrOneType)
       {
           pos_spit * spitPosTemp =  findSpitPos(ptrOneType, nodeSpitPos);
           if(spitPosTemp)
           {
               spitPosTemp->volume += nodeSpitPos->volume;
               delete nodeSpitPos;
           }
           else
           {
               ptrOneType->posListTail->next = nodeSpitPos;
               ptrOneType->posListTail = nodeSpitPos;
               ptrOneType->num ++ ;
           }

       }
       else
       {
           ptrOneType = new pos_one_type;
           memset(ptrOneType,0,sizeof(pos_one_type));
           ptrOneType->posListHead = nodeSpitPos;
           ptrOneType->posListTail = nodeSpitPos;
           ptrOneType->num = 1;
           ptrOneType->remainVolume = (*spitParamArr)[i].existv();
           ptrOneType->posType = (*spitParamArr)[i].pos().postype();
           ptrOneType->tipType = (*spitParamArr)[i].tiptype();
           if(paramListOut->listHead == NULL)
           {
               paramListOut->listHead = ptrOneType;
               paramListOut->listTail = ptrOneType;
           }
           else
           {
               paramListOut->listTail->next = ptrOneType;
               paramListOut->listTail  = ptrOneType;
           }
       }
   }

   *totalSpitVolume = spitVolume;
   return 0;

}

pos_one_type * findPosType(pos_type_list * listIn,int posTypeIn)
{
    pos_one_type * pstOneType = listIn->listHead;
    pos_one_type * pstRet = NULL;
    while(pstOneType!=NULL)
    {
        if(posTypeIn==pstOneType->posType)
        {
            pstRet = pstOneType;
            break;
        }
        pstOneType = pstOneType->next;

    }

    return pstRet;
}

void printDivideResult(pos_type_list * listIn)
{
   pos_one_type * pstOneType = listIn->listHead;
   pos_spit * pstOnePos = NULL;
   while(pstOneType)
   {
       printf("type:%d,num:%d\n",pstOneType->posType,pstOneType->num);
       pstOnePos = pstOneType->posListHead;
       while(pstOnePos)
       {
           printf("   index:%d,columnx:%d,rowy:%d\n",
           pstOnePos->index,
           pstOnePos->column_x,
           pstOnePos->row_y);
           
           pstOnePos=pstOnePos->next;
       }
       pstOneType = pstOneType->next;
   }
}

void clearSpitParamList(pos_type_list * listIn)
{
    pos_one_type * pstOneType = listIn->listHead;
    pos_one_type * pstOneTypeTmp= pstOneType;
    pos_spit * pstOnePos = NULL;
    pos_spit * pstOnePosTmp = NULL;
    while(pstOneType)
    {
        //printf("type:%d,num:%d\n",pstOneType->posType,pstOneType->num);
        pstOnePos = pstOneType->posListHead;
        while(pstOnePos)
        {
            //printf("   index:%d,columnx:%d,rowy:%d\n",
            //pstOnePos->index,
            //pstOnePos->column_x,
            //pstOnePos->row_y);
            
            pstOnePosTmp = pstOnePos;
            pstOnePos=pstOnePos->next;

            delete pstOnePosTmp;
        }

        pstOneTypeTmp = pstOneType;
        pstOneType = pstOneType->next;

        delete pstOneTypeTmp;
    }



}

pos_spit * findSpitPos(pos_one_type * spitPosOneType, const pos_spit * posSpitIn)
{
    pos_spit * posSpitRet = NULL;
    if(spitPosOneType==NULL || posSpitIn==NULL)
    {
        return posSpitRet;
    }
    pos_spit * posSpitTemp = spitPosOneType->posListHead;

    while(posSpitTemp)
    {
        if(posSpitTemp->column_x == posSpitIn->column_x
         &&posSpitTemp->row_y == posSpitIn->row_y
         &&posSpitTemp->index == posSpitIn->index)
         {
             posSpitRet = posSpitTemp;
             break;
         }
         posSpitTemp = posSpitTemp->next;
    }

    return posSpitRet;
}


int encodeSpitData_multi(int moduleTypeGrpc,pos_one_type * spitParamIn, char * buffOut,int isformultiIn, int remainVolume)
{
    //pstMsgHeadIn->paramLen = sizeof(location_layout) + (sizeof(int)<<1) + sizeof(int);
    location_layout locLayout;
    memset(&locLayout,0,sizeof(location_layout));

    GPRPC::Position posIn;
    posIn.set_column(spitParamIn->posListHead->column_x);
    posIn.set_row(spitParamIn->posListHead->row_y);
    posIn.set_index(GPRPC::Index(spitParamIn->posListHead->index) );
    posIn.set_postype(GPRPC::PosType(spitParamIn->posType));

    convertGRPCPos(moduleTypeGrpc, posIn,&locLayout);
    char * buffSend = buffOut;
//|xylayout|spitVolume|isformulti|remainVolume
    int currOffset = 0;//encodeMsgHead(pstMsgHeadIn,buffSend); 

    memcpy(buffSend,&locLayout,sizeof(location_layout));     
    currOffset += sizeof(location_layout);
    //currOffset += encodeInt(liquidType,buffSend+currOffset);
    printf("volume:%d\n",spitParamIn->posListHead->volume);
    memcpy(buffSend+currOffset,&spitParamIn->posListHead->volume,sizeof(int));
    currOffset += sizeof(int);
    memcpy(buffSend+currOffset,&isformultiIn,sizeof(int));
    currOffset += sizeof(int);
    //int remainVolume = 0;
    memcpy(buffSend+currOffset,&remainVolume,sizeof(int));
    currOffset += sizeof(int);
    memcpy(buffSend+currOffset,&spitParamIn->tipType,sizeof(int));
    currOffset += sizeof(int);
    printf("in encodeSpitData_multi, remainVolume:%d\n",remainVolume);
    
    int paramOnce = 0;

    pos_spit * pstPosSpit = spitParamIn->posListHead->next;
    location_layout locLayoutTmp;
    char deltax = 0;
    char deltay = 0;
    unsigned short volume1 = 0;
    char * ptrTempData = NULL;
    int numTemp = spitParamIn->num;
    while(pstPosSpit && numTemp>=1)
    {
        posIn.set_column(pstPosSpit->column_x);
        posIn.set_row(pstPosSpit->row_y);
        posIn.set_index(GPRPC::Index(pstPosSpit->index) );
        posIn.set_postype(GPRPC::PosType(spitParamIn->posType));

        convertGRPCPos(moduleTypeGrpc, posIn,&locLayoutTmp);
        deltax = locLayoutTmp.column_x - locLayout.column_x;
        deltay = locLayoutTmp.row_y - locLayout.row_y;
        volume1 = pstPosSpit->volume;

        memcpy(buffSend+currOffset,&deltax,sizeof(char));
        currOffset+=sizeof(char);
        memcpy(buffSend+currOffset,&deltay,sizeof(char));
        currOffset+=sizeof(char);
        memcpy(buffSend+currOffset,&volume1,sizeof(short));
        currOffset+=sizeof(short);
        printf("volume:%d\n",volume1);
        
        pstPosSpit = pstPosSpit->next;
        numTemp--;
    }
    
    return currOffset;
}


//the data this function calculated out, can be excuted at one time
void encodeSuck1SpitMData(int moduleGrpcIn, const void * pSuckParam, const void * pSpitParam,
void * dataOut, int *lenOut)
{
//suck|xylayout|liquidtype|suckVolume|isformulti|remainVolume
//spit|xylayout|spitVolume|isformulti|remainVolume|xyv|xyv   
    std::cout<<"enter in encodeSuck1SpitMData" <<std::endl;
    const GPRPC::MoveLiquidParam* suckParamIn =  (const GPRPC::MoveLiquidParam*)pSuckParam;

	int suckVolume = suckParamIn->volum();

	location_layout locLayout;	
    int convRet = convertGRPCPos(moduleGrpcIn, suckParamIn->pos(),&locLayout);

	if(convRet)
	{
	    printf("in encodeSuck1SpitMData, convert suck pos failed\n");
		*lenOut = 0;
		return;
	}

    printf("layout:type=%d,row_y:%d,colume_x:%d,ix:%d,iy:%d\n",
    locLayout.location_type,locLayout.row_y,locLayout.column_x,
    locLayout.indexX,locLayout.indexY);

    char * pBuffOut = (char *)dataOut;
//start encode for suck.
    memcpy(pBuffOut,&locLayout,sizeof(location_layout));
    pBuffOut += sizeof(location_layout);
    *lenOut += sizeof(location_layout);

    int liquidType = suckParamIn->viscosity();
    memcpy(pBuffOut,&liquidType,sizeof(int));
    pBuffOut += sizeof(int);
    *lenOut += sizeof(int);

    //int suckVolume = suckParamIn->volum();
    memcpy(pBuffOut,&suckVolume,sizeof(int));
    pBuffOut += sizeof(int);
    *lenOut += sizeof(int);

    int isForMulti = 1;
    memcpy(pBuffOut,&isForMulti,sizeof(int));
    pBuffOut += sizeof(int);
    *lenOut += sizeof(int);

    int remainVolume = suckParamIn->existv();
    memcpy(pBuffOut,&remainVolume,sizeof(int));
    pBuffOut += sizeof(int);
    *lenOut += sizeof(int); 
//end encode suck

//start encode spit
    pos_one_type * pSpitMOnce = (pos_one_type *)pSpitParam;
    *lenOut += encodeSpitData_multi(moduleGrpcIn,pSpitMOnce,pBuffOut,1,pSpitMOnce->remainVolume);
//end encode spit
}